package com.cencat.driver.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.result.Result;
import com.cencat.driver.entity.Driver;
import com.cencat.driver.service.DriverService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 司机控制器
 * 
 * @author cencat
 * @version 1.0
 * @since 2024-12-19
 */
@Tag(name = "司机管理", description = "司机相关接口")
@RestController
@RequestMapping("/api/driver")
@CrossOrigin(origins = "*")
public class DriverController {

    @Autowired
    private DriverService driverService;

    @Operation(summary = "分页查询司机列表", description = "根据条件分页查询司机信息")
    @GetMapping("/page")
    public Result<IPage<Driver>> getDriverPage(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "司机状态") @RequestParam(required = false) Integer driverStatus,
            @Parameter(description = "司机姓名") @RequestParam(required = false) String driverName,
            @Parameter(description = "手机号") @RequestParam(required = false) String phone,
            @Parameter(description = "车牌号") @RequestParam(required = false) String plateNumber,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        Page<Driver> page = new Page<>(current, size);
        IPage<Driver> result = driverService.getDriverPage(page, driverStatus, driverName, phone, plateNumber, startTime, endTime);
        return Result.success(result);
    }

    @Operation(summary = "根据ID获取司机详情", description = "根据司机ID获取详细信息")
    @GetMapping("/{id}")
    public Result<Driver> getDriverById(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id) {
        
        Driver driver = driverService.getById(id);
        if (driver == null) {
            return Result.error("司机不存在");
        }
        return Result.success(driver);
    }

    @Operation(summary = "根据手机号获取司机", description = "根据手机号获取司机信息")
    @GetMapping("/phone/{phone}")
    public Result<Driver> getDriverByPhone(
            @Parameter(description = "手机号", required = true) @PathVariable String phone) {
        
        Driver driver = driverService.getDriverByPhone(phone);
        if (driver == null) {
            return Result.error("司机不存在");
        }
        return Result.success(driver);
    }

    @Operation(summary = "创建司机", description = "创建新的司机")
    @PostMapping
    public Result<Boolean> createDriver(
            @Parameter(description = "司机信息", required = true) @RequestBody @Valid Driver driver) {
        
        boolean result = driverService.createDriver(driver);
        if (result) {
            return Result.success(true, "司机创建成功");
        }
        return Result.error("司机创建失败");
    }

    @Operation(summary = "更新司机信息", description = "更新司机的基本信息")
    @PutMapping("/{id}")
    public Result<Boolean> updateDriver(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "司机信息", required = true) @RequestBody @Valid Driver driver) {
        
        driver.setId(id);
        driver.setUpdateTime(LocalDateTime.now());
        boolean result = driverService.updateById(driver);
        if (result) {
            return Result.success(true, "司机信息更新成功");
        }
        return Result.error("司机信息更新失败");
    }

    @Operation(summary = "更新司机状态", description = "更新司机的状态")
    @PutMapping("/{id}/status")
    public Result<Boolean> updateDriverStatus(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "司机状态", required = true) @RequestParam @NotNull Integer driverStatus) {
        
        boolean result = driverService.updateDriverStatus(id, driverStatus, LocalDateTime.now());
        if (result) {
            return Result.success(true, "状态更新成功");
        }
        return Result.error("状态更新失败");
    }

    @Operation(summary = "分配司机", description = "为订单分配司机")
    @PutMapping("/{id}/assign")
    public Result<Boolean> assignDriver(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "订单ID", required = true) @RequestParam @NotNull Long orderId) {
        
        boolean result = driverService.assignDriver(id, orderId, LocalDateTime.now());
        if (result) {
            return Result.success(true, "司机分配成功");
        }
        return Result.error("司机分配失败");
    }

    @Operation(summary = "司机上线", description = "司机上线接单")
    @PutMapping("/{id}/online")
    public Result<Boolean> driverOnline(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "经度") @RequestParam(required = false) java.math.BigDecimal longitude,
            @Parameter(description = "纬度") @RequestParam(required = false) java.math.BigDecimal latitude) {
        
        boolean result = driverService.driverOnline(id, longitude, latitude, LocalDateTime.now());
        if (result) {
            return Result.success(true, "司机上线成功");
        }
        return Result.error("司机上线失败");
    }

    @Operation(summary = "司机下线", description = "司机下线停止接单")
    @PutMapping("/{id}/offline")
    public Result<Boolean> driverOffline(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id) {
        
        boolean result = driverService.driverOffline(id, LocalDateTime.now());
        if (result) {
            return Result.success(true, "司机下线成功");
        }
        return Result.error("司机下线失败");
    }

    @Operation(summary = "统计司机数量", description = "根据条件统计司机数量")
    @GetMapping("/count")
    public Result<Long> countDrivers(
            @Parameter(description = "司机状态") @RequestParam(required = false) Integer driverStatus,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        Long count = driverService.countDrivers(driverStatus, startTime, endTime);
        return Result.success(count);
    }

    @Operation(summary = "获取司机统计数据", description = "获取司机的统计信息")
    @GetMapping("/statistics")
    public Result<List<Map<String, Object>>> getDriverStatistics(
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        List<Map<String, Object>> statistics = driverService.getDriverStatistics(startTime, endTime);
        return Result.success(statistics);
    }

    @Operation(summary = "获取在线司机列表", description = "获取当前在线的司机列表")
    @GetMapping("/online")
    public Result<List<Driver>> getOnlineDrivers(
            @Parameter(description = "限制数量", example = "10") @RequestParam(defaultValue = "10") Integer limit) {
        
        List<Driver> drivers = driverService.getOnlineDrivers(limit);
        return Result.success(drivers);
    }

    @Operation(summary = "获取空闲司机列表", description = "获取当前空闲的司机列表")
    @GetMapping("/available")
    public Result<List<Driver>> getAvailableDrivers(
            @Parameter(description = "限制数量", example = "10") @RequestParam(defaultValue = "10") Integer limit) {
        
        List<Driver> drivers = driverService.getAvailableDrivers(limit);
        return Result.success(drivers);
    }

    @Operation(summary = "获取附近司机", description = "获取指定位置附近的司机")
    @GetMapping("/nearby")
    public Result<List<Driver>> getNearbyDrivers(
            @Parameter(description = "经度", required = true) @RequestParam @NotNull java.math.BigDecimal longitude,
            @Parameter(description = "纬度", required = true) @RequestParam @NotNull java.math.BigDecimal latitude,
            @Parameter(description = "半径(公里)", example = "5") @RequestParam(defaultValue = "5") Integer radius,
            @Parameter(description = "限制数量", example = "10") @RequestParam(defaultValue = "10") Integer limit) {
        
        List<Driver> drivers = driverService.getNearbyDrivers(longitude, latitude, radius, limit);
        return Result.success(drivers);
    }

    @Operation(summary = "获取司机订单统计", description = "获取司机的订单统计数据")
    @GetMapping("/{id}/order-stats")
    public Result<Map<String, Object>> getDriverOrderStats(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        Map<String, Object> stats = driverService.getDriverOrderStats(id, startTime, endTime);
        return Result.success(stats);
    }

    @Operation(summary = "获取司机收入统计", description = "获取司机的收入统计数据")
    @GetMapping("/{id}/income-stats")
    public Result<Map<String, Object>> getDriverIncomeStats(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        Map<String, Object> stats = driverService.getDriverIncomeStats(id, startTime, endTime);
        return Result.success(stats);
    }

    @Operation(summary = "获取司机评价统计", description = "获取司机的评价统计数据")
    @GetMapping("/{id}/rating-stats")
    public Result<Map<String, Object>> getDriverRatingStats(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id) {
        
        Map<String, Object> stats = driverService.getDriverRatingStats(id);
        return Result.success(stats);
    }

    @Operation(summary = "获取司机排行榜", description = "获取司机排行榜数据")
    @GetMapping("/ranking")
    public Result<List<Map<String, Object>>> getDriverRanking(
            @Parameter(description = "排行类型", example = "1") @RequestParam(defaultValue = "1") Integer rankingType,
            @Parameter(description = "限制数量", example = "10") @RequestParam(defaultValue = "10") Integer limit,
            @Parameter(description = "天数", example = "30") @RequestParam(defaultValue = "30") Integer days) {
        
        List<Map<String, Object>> ranking = driverService.getDriverRanking(rankingType, limit, days);
        return Result.success(ranking);
    }

    @Operation(summary = "批量更新司机状态", description = "批量更新多个司机的状态")
    @PutMapping("/batch-update-status")
    public Result<Boolean> batchUpdateDriverStatus(
            @Parameter(description = "司机ID列表", required = true) @RequestBody List<Long> driverIds,
            @Parameter(description = "司机状态", required = true) @RequestParam @NotNull Integer driverStatus) {
        
        boolean result = driverService.batchUpdateDriverStatus(driverIds, driverStatus, LocalDateTime.now());
        if (result) {
            return Result.success(true, "批量更新成功");
        }
        return Result.error("批量更新失败");
    }

    @Operation(summary = "更新司机位置", description = "更新司机的实时位置")
    @PutMapping("/{id}/location")
    public Result<Boolean> updateDriverLocation(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "经度", required = true) @RequestParam @NotNull java.math.BigDecimal longitude,
            @Parameter(description = "纬度", required = true) @RequestParam @NotNull java.math.BigDecimal latitude) {
        
        boolean result = driverService.updateDriverLocation(id, longitude, latitude, LocalDateTime.now());
        if (result) {
            return Result.success(true, "位置更新成功");
        }
        return Result.error("位置更新失败");
    }

    @Operation(summary = "获取司机详细信息", description = "获取司机的详细信息包括关联数据")
    @GetMapping("/{id}/detail")
    public Result<Map<String, Object>> getDriverDetailInfo(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id) {
        
        Map<String, Object> detail = driverService.getDriverDetailInfo(id);
        if (detail == null || detail.isEmpty()) {
            return Result.error("司机详情不存在");
        }
        return Result.success(detail);
    }

    @Operation(summary = "智能推荐司机", description = "根据订单信息智能推荐合适的司机")
    @PostMapping("/smart-recommend")
    public Result<List<Map<String, Object>>> smartRecommendDrivers(
            @Parameter(description = "起点经度", required = true) @RequestParam @NotNull java.math.BigDecimal startLongitude,
            @Parameter(description = "起点纬度", required = true) @RequestParam @NotNull java.math.BigDecimal startLatitude,
            @Parameter(description = "终点经度", required = true) @RequestParam @NotNull java.math.BigDecimal endLongitude,
            @Parameter(description = "终点纬度", required = true) @RequestParam @NotNull java.math.BigDecimal endLatitude,
            @Parameter(description = "服务类型") @RequestParam(required = false, defaultValue = "1") Integer serviceType,
            @Parameter(description = "限制数量", example = "5") @RequestParam(defaultValue = "5") Integer limit) {
        
        List<Map<String, Object>> drivers = driverService.smartRecommendDrivers(startLongitude, startLatitude, endLongitude, endLatitude, serviceType, limit);
        return Result.success(drivers);
    }

    @Operation(summary = "司机认证", description = "司机身份认证")
    @PutMapping("/{id}/verify")
    public Result<Boolean> verifyDriver(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "认证状态", required = true) @RequestParam @NotNull Integer verifyStatus,
            @Parameter(description = "认证备注") @RequestParam(required = false) String verifyRemark) {
        
        boolean result = driverService.verifyDriver(id, verifyStatus, verifyRemark, LocalDateTime.now());
        if (result) {
            return Result.success(true, "认证操作成功");
        }
        return Result.error("认证操作失败");
    }

    @Operation(summary = "获取司机工作时长统计", description = "获取司机的工作时长统计数据")
    @GetMapping("/{id}/work-time-stats")
    public Result<Map<String, Object>> getDriverWorkTimeStats(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        Map<String, Object> stats = driverService.getDriverWorkTimeStats(id, startTime, endTime);
        return Result.success(stats);
    }

    @Operation(summary = "获取司机性能统计", description = "获取司机的性能统计数据")
    @GetMapping("/{id}/performance-stats")
    public Result<Map<String, Object>> getDriverPerformanceStats(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "天数", example = "30") @RequestParam(defaultValue = "30") Integer days) {
        
        Map<String, Object> stats = driverService.getDriverPerformanceStats(id, days);
        return Result.success(stats);
    }

    @Operation(summary = "导出司机数据", description = "导出司机数据到Excel")
    @GetMapping("/export")
    public Result<List<Map<String, Object>>> exportDriverData(
            @Parameter(description = "司机ID列表") @RequestParam(required = false) List<Long> driverIds,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        List<Map<String, Object>> data = driverService.exportDriverData(driverIds, startTime, endTime);
        return Result.success(data);
    }

    @Operation(summary = "获取司机车辆信息", description = "获取司机的车辆信息")
    @GetMapping("/{id}/vehicle")
    public Result<Map<String, Object>> getDriverVehicleInfo(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id) {
        
        Map<String, Object> vehicle = driverService.getDriverVehicleInfo(id);
        return Result.success(vehicle);
    }

    @Operation(summary = "更新司机车辆信息", description = "更新司机的车辆信息")
    @PutMapping("/{id}/vehicle")
    public Result<Boolean> updateDriverVehicleInfo(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "车辆信息", required = true) @RequestBody Map<String, Object> vehicleInfo) {
        
        boolean result = driverService.updateDriverVehicleInfo(id, vehicleInfo, LocalDateTime.now());
        if (result) {
            return Result.success(true, "车辆信息更新成功");
        }
        return Result.error("车辆信息更新失败");
    }

    @Operation(summary = "获取司机历史轨迹", description = "获取司机的历史行驶轨迹")
    @GetMapping("/{id}/track")
    public Result<List<Map<String, Object>>> getDriverTrack(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        List<Map<String, Object>> track = driverService.getDriverTrack(id, startTime, endTime);
        return Result.success(track);
    }

    @Operation(summary = "司机签到", description = "司机每日签到")
    @PostMapping("/{id}/checkin")
    public Result<Boolean> driverCheckin(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "签到位置经度") @RequestParam(required = false) java.math.BigDecimal longitude,
            @Parameter(description = "签到位置纬度") @RequestParam(required = false) java.math.BigDecimal latitude) {
        
        boolean result = driverService.driverCheckin(id, longitude, latitude, LocalDateTime.now());
        if (result) {
            return Result.success(true, "签到成功");
        }
        return Result.error("签到失败");
    }

    @Operation(summary = "获取司机签到记录", description = "获取司机的签到记录")
    @GetMapping("/{id}/checkin-records")
    public Result<List<Map<String, Object>>> getDriverCheckinRecords(
            @Parameter(description = "司机ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制数量", example = "30") @RequestParam(defaultValue = "30") Integer limit) {
        
        List<Map<String, Object>> records = driverService.getDriverCheckinRecords(id, startTime, endTime, limit);
        return Result.success(records);
    }

}